package br.ufc.dc.redes.proxy;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class HttpResponse {
	final static String CRLF = "\r\n";
	/** atribui o tamanho do buffer para ler o objeto */
	final static int BUF_SIZE = 8192;
	/**
	 * Tamanho maximo do objeto que esse proxy pode aguentar. Para o momento
	 * onde se atribuiu 100 KB
	 */
	final static int MAX_OBJECT_SIZE = 100000;
	/** Replicar status e cabe�alhos */
	private String version;
	private int status;
	private String statusLine = "";
	private String headers = "";
	private Integer contentLength = null;
	/* Corpo da replica��o */
	private byte[] body = new byte[MAX_OBJECT_SIZE];

	/** Ler a resposta do servidor */
	public HttpResponse(DataInputStream fromServer) {
		/* Comprimento do objeto */
		BufferedReader reader = new BufferedReader(new InputStreamReader(
				fromServer));
		try {
			headers = readHeader(reader);
		} catch (IOException e) {
			System.out.println("Error reading headers from server: " + e);
			e.printStackTrace();
			return;
		}
		try {
			setBody(readBody(fromServer));
		} catch (IOException e) {
			System.out.println("Error reading response body: " + e);
			e.printStackTrace();
		}
	}

	private String readHeader(BufferedReader reader) throws IOException {
		String header = "";
		String line = reader.readLine();
		statusLine = line;
		while (line.length() != 0) {
			line = reader.readLine();
			headers += line + CRLF;
			if (line.toLowerCase().startsWith("content-length:")) {
				contentLength = Integer.parseInt(line.split(" ")[1]);
			}
		}
		return header;
	}

	private byte[] readBody(DataInputStream fromServer) throws IOException {
		int bytesRead = 0;
		byte[] body = new byte[MAX_OBJECT_SIZE];
		byte buf[] = new byte[BUF_SIZE];
		/*
		 * Se nos n�o pegar-mos o cabe�alho de Content-Lenght, fica num loop
		 * at� a conex�o ser fechada
		 */
		boolean loop = false;
		if (contentLength == null) {
			loop = true;
		}

		int res = Integer.MAX_VALUE;
		while (bytesRead < contentLength || loop) {
			/* Ler em dados binarios */
			res = fromServer.read(buf, 0, BUF_SIZE);
			if (res < 0) {
				break;
			}
			/*
			 * Copia os bytes para o corpo. N�o pode exceder o tamanho maximo
			 * do objeto
			 */
			for (int i = 0; i < res && (i + bytesRead) < MAX_OBJECT_SIZE; i++) {
				body[bytesRead + i] = buf[i];
			}
			bytesRead += res;
		}
		return body;
	}

	/**
	 * Converter a resposta numa string para envia-la mais facilmente. Converter
	 * somente o cabe�alho
	 */
	public String toString() {
		String res = "";
		res = statusLine + CRLF;
		res += headers;
		res += CRLF;
		return res;
	}

	public byte[] getBody() {
		return body;
	}

	public void setBody(byte[] body) {
		this.body = body;
	}
}
